﻿#if !XBOX

#region using statements
using System;
using System.IO;
using SoundLibrary.Converter;
using SoundLibrary.BeatDetection;
using System.Runtime.InteropServices;
#endregion

namespace FMOD
{
    public sealed class Mp3Player
    {
        #region Fields and Properties

        private const int SPECTRUMSIZE = 512;
        private const int WAVEDATASIZE = 256;

        private FMOD.System system = null;
        private FMOD.Sound sound = null;
        private FMOD.Channel channel = null;
        public FMOD.TAG Information;

        private float[] spectrum = new float[SPECTRUMSIZE];
        private float[] wavedata = new float[WAVEDATASIZE];
        public bool IsPlaying = false;
        private string filename;

        FMOD.TAG tag;
        private string[] information;

        public string[] TagInformation
        {
            get { return information; }
        }

        public string Artist
        {
            get {
                if (information[0] != null)
                    return information[0];
                return "Unknow";
            }
        }

        public string Title
        {
            get
            {
                if (information[1] != null)
                    return information[1];
                return "Unknow";
            }
        }

        public string Album
        {
            get
            {
                if (information[2] != null)
                    return information[2];
                return "Unknow";
            }
        }
        
        public string SongFilename
        {
            get { return filename; }
            set { filename = value; }
        }

        public float[] Spectrum
        {
            get { return spectrum; }
        }
        #endregion

        #region Initializing
        public Mp3Player()
        {
            FMOD.RESULT result;

            result = FMOD.Factory.System_Create(ref system);
            ERRCHECK(result);

            result = system.init(32, FMOD.INITFLAG.NORMAL, (IntPtr)null);
            ERRCHECK(result);

            information = new string[3];
        }

        public void Initialize()
        {
            if (this.filename != null)
            {
                FMOD.RESULT result = system.createStream(filename, FMOD.MODE.SOFTWARE | FMOD.MODE._2D, ref sound);
                ERRCHECK(result);
            }
        }
        #endregion

        #region player methods
        public void PlaySong()
        {
            FMOD.RESULT result;

            if (IsPlaying == false)
            {
                result = system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel);
                ERRCHECK(result);

                IsPlaying = true;
            }
        }

        public void Stop()
        {
            FMOD.RESULT result;

            if (channel != null)
            {
                result = channel.stop();
                ERRCHECK(result);

                IsPlaying = false;
            }
        }

        public void PauseSong()
        {
            bool paused = false;
            if (channel != null)
            {
                RESULT result = channel.getPaused(ref paused);
                ERRCHECK(result);
                result = channel.setPaused(!paused);
                ERRCHECK(result);
            }
            //IsPlaying = !paused;
        }

        public void SetSpectrum()
        {
            int numchannels = 0;
            int dummy = 0;
            FMOD.SOUND_FORMAT dummyformat = FMOD.SOUND_FORMAT.NONE;
            FMOD.DSP_RESAMPLER dummyresampler = FMOD.DSP_RESAMPLER.LINEAR;

            system.getSoftwareFormat(ref dummy, ref dummyformat, ref numchannels, ref dummy, ref dummyresampler, ref dummy);

            for (int count = 0; count < numchannels; count++)
            {
                system.getSpectrum(spectrum, SPECTRUMSIZE, count, FMOD.DSP_FFT_WINDOW.TRIANGLE);
            }
        }

        public void ReadTags()
        {
            tag = new FMOD.TAG();
            FMOD.RESULT result;

            result = sound.getTag("ARTIST", 0, ref tag);
            ERRCHECK(result);
            information[0] = Marshal.PtrToStringAnsi(tag.data);

            result = sound.getTag("TITLE", 0, ref tag);
            ERRCHECK(result);
            information[1] = Marshal.PtrToStringAnsi(tag.data);

            result = sound.getTag("ALBUM", 0, ref tag);
            ERRCHECK(result);
            information[2] = Marshal.PtrToStringAnsi(tag.data);
        }

        public bool SongFinished()
        {
            FMOD.RESULT result;
            bool playing = false;

            result = channel.isPlaying(ref playing);
            ERRCHECK(result);

            if (!playing)
            {
                IsPlaying = false;
            }

            return !playing;
        }

        #endregion

        #region auxiliar methods
        private void ERRCHECK(FMOD.RESULT result)
        {
            if (result != FMOD.RESULT.OK)
            {
                Console.WriteLine("FMOD error! " + result + " - " + FMOD.Error.String(result));
                //Environment.Exit(-1);
            }
        }
        #endregion

    }
}
#endif